package com.backedserver.controller.login;

import com.backedserver.base.CaffeineUtils;
import com.common.constants.Constants;
import com.common.entity.user.SecurityUser;
import com.common.entity.user.UserEntity;
import com.common.global.BizException;
import com.common.global.BizServiceEnum;
import com.common.global.CommonEnum;
import com.common.global.JwtTokenException;
import com.common.requestvo.LoginReqVo;
import com.common.requestvo.system.ChangePasswordReqVo;
import com.common.requestvo.system.RefreshTokenReqVo;
import com.common.service.system.UserService;
import com.common.utils.JwtTokenUtils;
import com.common.utils.ResultVoUtil;
import com.common.utils.TokenUtils;
import com.common.vo.ResultVo;
import com.common.vo.system.LoginResultVo;
import com.common.vo.system.UserResultVo;
import com.google.common.collect.Maps;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentMap;

/**
 * 登录 Controller
 *
 * @author johnny
 * @create 2020-07-10 下午4:14
 **/
@RestController
@Slf4j
@RequestMapping("/auth")
@Api(tags = "登录模块")
public class LoginController {

    @Autowired
    private UserService userService;

    @Autowired
    private RedisTemplate redisTemplate;

    @GetMapping("/cache2")
    public ResultVo cache2() {
        ConcurrentMap<String, String> stringStringConcurrentMap = CaffeineUtils.getTokenCache().asMap();
        Map<String, String> map = new HashMap<>();
        stringStringConcurrentMap.forEach(map::put);
        return ResultVoUtil.success(map);
    }

    @GetMapping("/cache")
    public ResultVo cache() {

//        Map<String, String> hlp = createToken(25L, "hlp",null);
//
//        log.info("hlp : {}", hlp);
//
//        ConcurrentMap<String, String> stringStringConcurrentMap = CaffeineUtils.getTokenCache().asMap();
//        Map<String, String> map = new HashMap<>();
//        stringStringConcurrentMap.forEach(map::put);
        //return ResultVoUtil.success(map);
        return ResultVoUtil.success();
    }

    @PostMapping("/login")
    @ApiOperation(value = "系统登录")
    public ResultVo login(@RequestBody LoginReqVo loginReqVo) {
        log.info("【loginReqVo： {}】", loginReqVo);
        UserResultVo userResultVo = userService.findByUserName(loginReqVo.getUsername());
        if (userResultVo != null) {
            if (userResultVo.getPassword().equals(loginReqVo.getPassword())) {
                if (userResultVo.getEnable() != null && userResultVo.getEnable()) {
                    SecurityUser securityUser = new SecurityUser();
                    securityUser.setUserId(userResultVo.getId());
                    securityUser.setUsername(userResultVo.getUsername());
                    securityUser.setRoles(userResultVo.getRoles());
                    Map<String, String> resultMap = createToken(securityUser);
                    LoginResultVo loginResultVo = new LoginResultVo();
                    loginResultVo.setToken(resultMap.get(Constants.ACCESS_TOKEN));
                    loginResultVo.setRefreshToken(resultMap.get(Constants.REFRESH_TOKEN));
                    loginResultVo.setUserResultVo(userResultVo);
                    return ResultVoUtil.success(loginResultVo);
                } else {
                    throw new BizException(BizServiceEnum.ACCOUNT_NOT_ENABLE);
                }
            }
        } else {
            return ResultVoUtil.loginFail();
        }
        return ResultVoUtil.loginFail();
    }

    private Map<String, String> createToken(SecurityUser securityUser) {
        Map<String, String> resultMap = Maps.newHashMap();
        String jwtToken = JwtTokenUtils.getJwtToken(securityUser);
        resultMap.put(Constants.ACCESS_TOKEN, jwtToken);
        String refreshJwtToken = JwtTokenUtils.getRefreshJwtToken(securityUser);
        resultMap.put(Constants.REFRESH_TOKEN, refreshJwtToken);
//        CaffeineUtils.getTokenCache2().put(securityUser.getUserId() + "_" + securityUser.getUsername(),
//                refreshJwtToken);
        //redisTemplate.opsForValue().set(securityUser.getUserId() + "_" + securityUser.getUsername(),
        //refreshJwtToken);
        log.info("【create oldRefreshToken：{}】", refreshJwtToken);
        return resultMap;
    }

    @PostMapping("/refreshToken")
    @ApiOperation(value = "刷新Token")
    public ResultVo refreshToken(@RequestBody RefreshTokenReqVo refreshTokenReqVo) {
        String refreshToken = refreshTokenReqVo.getRefreshToken();
        if (JwtTokenUtils.validate(refreshToken)) {
            String username = JwtTokenUtils.getUserNameFromToken(refreshToken);
            Long userId = JwtTokenUtils.getUserIdFromToken(refreshToken);
            List<String> roles = JwtTokenUtils.getUserRolesFromToken(refreshToken);

            //String oldRefreshToken = CaffeineUtils.getTokenCache2().get(userId + "_" + username);
            //String oldRefreshToken = (String) redisTemplate.opsForValue().get(userId + "_" + username);
            log.info("【refreshToken  oldRefreshToken：{}】", refreshToken);
            // if (StringUtils.isNotEmpty(oldRefreshToken) && oldRefreshToken.equalsIgnoreCase(refreshToken)) {
            SecurityUser securityUser = new SecurityUser();
            securityUser.setUserId(userId);
            securityUser.setUsername(username);
            securityUser.setRoles(roles);
            Map<String, String> resultMap = createToken(securityUser);
            return ResultVoUtil.success(resultMap);
//            } else {
//                throw new JwtTokenException(CommonEnum.REFRESH_TOKEN_EXPIRED);
//            }
        } else {
            //未登录，告诉前台去登录
            throw new JwtTokenException(CommonEnum.REFRESH_TOKEN_EXPIRED);
        }
    }


    @PostMapping("/changePassword")
    @ApiOperation(value = "修改密码")
    public ResultVo changePassword(@RequestBody ChangePasswordReqVo changePasswordReqVo, HttpServletRequest request) {
        Long userId = JwtTokenUtils.getUserIdFromToken(TokenUtils.getTokenFromRequest(request));
        if (userId == 0L) {
            throw new BizException(CommonEnum.ID_NOT_NULL);
        }
        UserEntity userEntity = userService.findByUserId(userId);
        if (userEntity.getPassword().equals(changePasswordReqVo.getOldPassword())) {
            userEntity.setPassword(changePasswordReqVo.getNewPassword());
            userService.save(userEntity);
        } else {
            throw new BizException(CommonEnum.OLD_PASSWORD_ERROR);
        }
        return ResultVoUtil.success();
    }

}